package name.cyrax.red.jpv.impl.funcs.core;

import name.cyrax.red.jpv.api.adapters.NumericAccessor;
import name.cyrax.red.jpv.api.adapters.NumericAdapter;
import name.cyrax.red.jpv.api.funcs.FunctorImplementor;
import name.cyrax.red.jpv.api.funcs.Invocable;
import name.cyrax.red.jpv.api.funcs.InvocationContext;
import name.cyrax.red.jpv.api.vectors.VectorFactory;
import name.cyrax.red.jpv.impl.adapters.NumericImpl;
import name.cyrax.red.jpv.impl.funcs.InvocableImpl;

public abstract class FunctorAbstractUnaryImpl<A extends NumericAdapter> extends FunctorImpl<A, A>
	implements FunctorImplementor<A>
{
	protected class UnaryInvocableImpl<V extends Number> extends InvocableImpl<V> {
		protected final Invocable<?> param0;

		public UnaryInvocableImpl(VectorFactory<V> factory, Invocable<?> param0)
		{
			super(factory); 
			this.param0 = param0;
		}
		
		public UnaryInvocableImpl(Invocable<V> param0)
		{
			super(param0.factory());
			this.param0 = param0;
		}
		
		@Override public <T> T access(InvocationContext context, NumericAccessor<T> accessor)
		{
			A adapter = newImplementation(context, param0);
			return adapter.detectType(accessor);
		}

		@Override public Invocable<?> getInvocableParam(int index)
		{
			return NumericImpl.switchOf(index, param0);
		}

		@Override protected String getName()
		{
			return FunctorAbstractUnaryImpl.this.getName();
		}
	};
	
	@Override protected final FunctorImplementor<A> getPrimaryFunctorImplementor()
	{
		return this;
	}
}
